﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TransformerManager.EF.Database;
using TransformerManager.EF.Models;
using TransformerManager.Shared.ResourceParameters;
using TransformerManager.Shared.Helper;

namespace TransformerManager.Shared.Servers
{
    public class TransformerRepository : ITransformerRepository
    {
        private readonly AppDBContext _context;
        public TransformerRepository(AppDBContext appDBContext)
        {
            _context = appDBContext;
        }

        /// <summary>
        /// 根据传入的参数来筛选数据库内容
        /// </summary>
        /// <param name="trResourceParams">筛选参数</param>
        /// <param name="result">IQueryable数据</param>
        /// <returns>筛选后的IQueryable数据</returns>
        private IQueryable<Transformer> ConditionalFileter(
            TransformerResourceParameters trResourceParams, 
            IQueryable<Transformer> result)
        {
            // ---------------Basic Information---------------
            if (trResourceParams.BasicInfos != null)
            {
                var basicInfosResourceParams = trResourceParams.BasicInfos;

                result = string.IsNullOrEmpty(basicInfosResourceParams.ProjectNumber) ?
                    result : result.Where(t => t.BasicInfos.ProjectNumber == basicInfosResourceParams.ProjectNumber);

                result = string.IsNullOrEmpty(basicInfosResourceParams.ProjectName) ?
                    result : result.Where(t => t.BasicInfos.ProjectName.Contains(basicInfosResourceParams.ProjectName));

                result = string.IsNullOrEmpty(basicInfosResourceParams.ApplicationType) ?
                    result : result.Where(t => t.BasicInfos.ApplicationType == basicInfosResourceParams.ApplicationType);

                result = basicInfosResourceParams.Capacity == -1 ?
                    result : result.Where(t => t.BasicInfos.Capacity == basicInfosResourceParams.Capacity);

                result = basicInfosResourceParams.RatedFrequency == -1 ?
                    result : result.Where(t => t.BasicInfos.RatedFrequency == basicInfosResourceParams.RatedFrequency);

                result = string.IsNullOrEmpty(basicInfosResourceParams.VectorGroupSym) ?
                    result : result.Where(t => t.BasicInfos.VectorGroupSym == basicInfosResourceParams.VectorGroupSym);

                result = basicInfosResourceParams.RatedHV == -1 ?
                    result : result.Where(t => t.BasicInfos.RatedHV == basicInfosResourceParams.RatedHV);

                result = basicInfosResourceParams.RatedLV == -1 ?
                    result : result.Where(t => t.BasicInfos.RatedLV == basicInfosResourceParams.RatedLV);

                result = string.IsNullOrEmpty(basicInfosResourceParams.RegionType) ?
                    result : result.Where(t => t.BasicInfos.RegionType == basicInfosResourceParams.RegionType);

                result = string.IsNullOrEmpty(basicInfosResourceParams.ProdTag) ?
                    result : result.Where(t => t.BasicInfos.ProdTag == basicInfosResourceParams.ProdTag);

                result = string.IsNullOrEmpty(basicInfosResourceParams.Housing) ?
                    result : result.Where(t => t.BasicInfos.Housing == basicInfosResourceParams.Housing);

                result = string.IsNullOrEmpty(basicInfosResourceParams.InsulationMaterial) ?
                    result : result.Where(t => t.BasicInfos.InsulationMaterial == basicInfosResourceParams.InsulationMaterial);
            }

            // ---------------TapChanger Information---------------
            if (trResourceParams.TapChanger != null)
            {
                var tcResourceParams = trResourceParams.TapChanger;

                result = string.IsNullOrEmpty(tcResourceParams.ProdType) ?
                    result : result.Where(t => t.BasicInfos.TapChangers
                    .Any(t => t.ProdType.Contains(tcResourceParams.ProdType)));

                result = string.IsNullOrEmpty(tcResourceParams.TapChangerPosition) ?
                    result : result.Where(t => t.BasicInfos.TapChangers
                    .Any(t => t.TapChangerPosition == tcResourceParams.TapChangerPosition));

                result = string.IsNullOrEmpty(tcResourceParams.OperationType) ?
                    result : result.Where(t => t.BasicInfos.TapChangers
                    .Any(t => t.OperationType == tcResourceParams.OperationType));

                result = string.IsNullOrEmpty(tcResourceParams.Manufacturer) ?
                    result : result.Where(t => t.BasicInfos.TapChangers
                    .Any(t => t.Manufacturer == tcResourceParams.Manufacturer));
            }

            // ---------------Dome Information---------------
            if (trResourceParams.Dome != null)
            {
                var domeResourceParams = trResourceParams.Dome;

                result = string.IsNullOrEmpty(domeResourceParams.DomeAssembleType) ?
                    result : result.Where(t => t.BasicInfos.Domes
                    .Any(t => t.DomeAssembleType == domeResourceParams.DomeAssembleType));

                result = domeResourceParams.InnerDiameter == -1 ?
                    result : result.Where(t => t.BasicInfos.Domes
                    .Any(t => t.InnerDiameter == domeResourceParams.InnerDiameter));
            }

            // ---------------Bushing Information---------------
            if (trResourceParams.Bushing != null)
            {
                var bushingResourceParams = trResourceParams.Bushing;

                result = bushingResourceParams.CTTotalAssembleHeight == -1 ?
                    result : result.Where(t => t.BasicInfos.Bushings
                    .Any(t => t.CTTotalAssembleHeight == bushingResourceParams.CTTotalAssembleHeight));

                result = string.IsNullOrEmpty(bushingResourceParams.InsulatorColor) ?
                    result : result.Where(t => t.BasicInfos.Bushings
                    .Any(t => t.InsulatorColor == bushingResourceParams.InsulatorColor));

                result = string.IsNullOrEmpty(bushingResourceParams.ProdType) ?
                    result : result.Where(t => t.BasicInfos.Bushings
                    .Any(t => t.ProdType.Contains(bushingResourceParams.ProdType)));

                result = string.IsNullOrEmpty(bushingResourceParams.RefStandard) ?
                    result : result.Where(t => t.BasicInfos.Bushings
                    .Any(t => t.RefStandard == bushingResourceParams.RefStandard));

                result = string.IsNullOrEmpty(bushingResourceParams.Manufacturer) ?
                    result : result.Where(t => t.BasicInfos.Bushings
                    .Any(t => t.Manufacturer == bushingResourceParams.Manufacturer));

            }

            // ---------------Tank Information---------------
            if (trResourceParams.Tank != null)
            {
                var tankResourceParams = trResourceParams.Tank;

                result = string.IsNullOrEmpty(tankResourceParams.TankShape) ?
                    result : result.Where(t => t.Tank.TankShape == tankResourceParams.TankShape);

                result = string.IsNullOrEmpty(tankResourceParams.FrameType) ?
                    result : result.Where(t => t.Tank.FrameType == tankResourceParams.FrameType);

                result = string.IsNullOrEmpty(tankResourceParams.RadButterflyValveType) ?
                    result : result.Where(t => t.Tank.RadButterflyValveType == tankResourceParams.RadButterflyValveType);

                result = string.IsNullOrEmpty(tankResourceParams.OltcIndent) ?
                    result : result.Where(t => t.Tank.OltcIndent == tankResourceParams.OltcIndent);

                result = string.IsNullOrEmpty(tankResourceParams.HVLVIndent) ?
                    result : result.Where(t => t.Tank.HVLVIndent == tankResourceParams.HVLVIndent);

                result = string.IsNullOrEmpty(tankResourceParams.ActbDome) ?
                    result : result.Where(t => t.Tank.ActbDome == tankResourceParams.ActbDome);

                result = string.IsNullOrEmpty(tankResourceParams.OctbDome) ?
                    result : result.Where(t => t.Tank.OctbDome == tankResourceParams.OctbDome);

                result = tankResourceParams.HasWheel ?
                    result.Where(t => t.Tank.HasWheel == true) :
                    result.Where(t => t.Tank.HasWheel == false);

                result = tankResourceParams.HasNeutralDome ?
                    result.Where(t => t.Tank.HasNeutralDome == true) :
                    result.Where(t => t.Tank.HasNeutralDome == false);

                result = tankResourceParams.HasEnlargeSideWall1 ?
                    result.Where(t => t.Tank.HasEnlargeSideWall1 == true) :
                    result.Where(t => t.Tank.HasEnlargeSideWall1 == false);

                result = tankResourceParams.HasEnlargeSideWall2 ?
                    result.Where(t => t.Tank.HasEnlargeSideWall2 == true) :
                    result.Where(t => t.Tank.HasEnlargeSideWall2 == false);

                result = tankResourceParams.HasEnlargeSideWall3 ?
                    result.Where(t => t.Tank.HasEnlargeSideWall3 == true) :
                    result.Where(t => t.Tank.HasEnlargeSideWall3 == false);

                result = tankResourceParams.HasEnlargeSideWall4 ?
                    result.Where(t => t.Tank.HasEnlargeSideWall4 == true) :
                    result.Where(t => t.Tank.HasEnlargeSideWall4 == false);
            }

            // ---------------Conservator Information---------------
            if (trResourceParams.Conservator != null)
            {
                var conservatorResourceParams = trResourceParams.Conservator;

                result = string.IsNullOrEmpty(conservatorResourceParams.ConservatorType) ?
                    result : result.Where(t => t.Conservator.ConservatorType == conservatorResourceParams.ConservatorType);

                result = conservatorResourceParams.HasTCConservator ?
                    result.Where(t => t.Conservator.HasTCConservator == true)
                    : result.Where(t => t.Conservator.HasTCConservator == false);

                result = string.IsNullOrEmpty(conservatorResourceParams.Dimension) ?
                    result : result.Where(t => t.Conservator.Dimension == conservatorResourceParams.Dimension);
            }

            // ---------------CoolingSystem Information---------------
            if (trResourceParams.CoolingSystem != null)
            {
                var coolSysResourceParams = trResourceParams.CoolingSystem;

                result = string.IsNullOrEmpty(coolSysResourceParams.CoolingType) ?
                    result : result.Where(t => t.CoolingSystem.CoolingType
                    .Contains(coolSysResourceParams.CoolingType));

                result = string.IsNullOrEmpty(coolSysResourceParams.CoolingLayout) ?
                    result : result.Where(t => t.CoolingSystem.CoolingLayout
                    == coolSysResourceParams.CoolingLayout);

                result = string.IsNullOrEmpty(coolSysResourceParams.RadiatorType) ?
                    result : result.Where(t => t.CoolingSystem.RadiatorType.Contains(
                    coolSysResourceParams.RadiatorType));

                result = string.IsNullOrEmpty(coolSysResourceParams.RadiatorManufacturer) ?
                    result : result.Where(t => t.CoolingSystem.RadiatorManufacturer
                    == coolSysResourceParams.RadiatorManufacturer);

                result = string.IsNullOrEmpty(coolSysResourceParams.FanType) ?
                    result : result.Where(t => t.CoolingSystem.FanType.Contains(
                    coolSysResourceParams.FanType));

                result = string.IsNullOrEmpty(coolSysResourceParams.FanManufacturer) ?
                    result : result.Where(t => t.CoolingSystem.FanManufacturer
                    == coolSysResourceParams.FanManufacturer);

                result = string.IsNullOrEmpty(coolSysResourceParams.CoolerType) ?
                    result : result.Where(t => t.CoolingSystem.CoolerType.Contains(
                    coolSysResourceParams.CoolerType));

                result = string.IsNullOrEmpty(coolSysResourceParams.CoolerManufacturer) ?
                    result : result.Where(t => t.CoolingSystem.CoolerManufacturer
                    == coolSysResourceParams.CoolerManufacturer);
            }

            // ---------------Accessories Information---------------
            if (trResourceParams.Accessories != null)
            {
                var accResourceParams = trResourceParams.Accessories;

                result = string.IsNullOrEmpty(accResourceParams.BoltMaterial) ?
                    result : result.Where(t => t.Accessories.BoltMaterial == accResourceParams.BoltMaterial);

                result = string.IsNullOrEmpty(accResourceParams.SealMaterial) ?
                    result : result.Where(t => t.Accessories.SealMaterial == accResourceParams.SealMaterial);

            }

            // ---------------AccesstoryEquipment Information---------------

            if (trResourceParams.AccesstoryEquipment != null)
            {
                var accEqResourceParams = trResourceParams.AccesstoryEquipment;

                result = string.IsNullOrEmpty(accEqResourceParams.AccessoryEquName) ?
                    result : result.Where(t => t.Accessories.AccesstoryEquipments
                    .Any(a => a.AccessoryEquName == accEqResourceParams.AccessoryEquName));

                result = string.IsNullOrEmpty(accEqResourceParams.ProdType) ?
                    result : result.Where(t => t.Accessories.AccesstoryEquipments
                    .Any(a => a.ProdType.Contains(accEqResourceParams.ProdType)));

                result = string.IsNullOrEmpty(accEqResourceParams.Manufacturer) ?
                    result : result.Where(t => t.Accessories.AccesstoryEquipments
                    .Any(a => a.Manufacturer.Contains(accEqResourceParams.Manufacturer)));
            }

            // ---------------Lead Information---------------
            if (trResourceParams.Lead != null)
            {
                var leadResourceParams = trResourceParams.Lead;

                result = leadResourceParams.HVCurrent == -1 ?
                    result : result.Where(t => t.Lead.HVCurrent == leadResourceParams.HVCurrent);

                result = leadResourceParams.LVCurrent == -1 ?
                    result : result.Where(t => t.Lead.LVCurrent == leadResourceParams.LVCurrent);

                result = leadResourceParams.MVCurrent == -1 ?
                    result : result.Where(t => t.Lead.MVCurrent == leadResourceParams.MVCurrent);

                result = leadResourceParams.IsCenterInfeed ?
                    result.Where(t => t.Lead.IsCenterInfeed == true)
                    : result.Where(t => t.Lead.IsCenterInfeed == false);

                result = string.IsNullOrEmpty(leadResourceParams.HVOutlet) ?
                    result : result.Where(t => t.Lead.HVOutlet == leadResourceParams.HVOutlet);

                result = string.IsNullOrEmpty(leadResourceParams.HVROutlet) ?
                    result : result.Where(t => t.Lead.HVROutlet == leadResourceParams.HVROutlet);

                result = string.IsNullOrEmpty(leadResourceParams.LVOutlet) ?
                    result : result.Where(t => t.Lead.LVOutlet == leadResourceParams.LVOutlet);

                result = string.IsNullOrEmpty(leadResourceParams.MVOutlet) ?
                    result : result.Where(t => t.Lead.MVOutlet == leadResourceParams.MVOutlet);

                result = string.IsNullOrEmpty(leadResourceParams.HVBushingPos) ?
                    result : result.Where(t => t.Lead.HVBushingPos == leadResourceParams.HVBushingPos);

                result = string.IsNullOrEmpty(leadResourceParams.LVBushingPos) ?
                    result : result.Where(t => t.Lead.LVBushingPos == leadResourceParams.LVBushingPos);

                result = string.IsNullOrEmpty(leadResourceParams.MVBushingPos) ?
                    result : result.Where(t => t.Lead.MVBushingPos == leadResourceParams.MVBushingPos);
            }

            // ---------------LeadConnector Information---------------
            if (trResourceParams.LeadConnector != null)
            {
                var leadConnResourceParams = trResourceParams.LeadConnector;

                result = string.IsNullOrEmpty(leadConnResourceParams.LeadName) ?
                    result : result.Where(t => t.Lead.LeadConnectors
                    .Any(l => l.LeadName == leadConnResourceParams.LeadName));

                result = string.IsNullOrEmpty(leadConnResourceParams.LeadType) ?
                    result : result.Where(t => t.Lead.LeadConnectors
                    .Any(l => l.LeadType == leadConnResourceParams.LeadType));

                result = string.IsNullOrEmpty(leadConnResourceParams.LeadDimensionType) ?
                    result : result.Where(t => t.Lead.LeadConnectors
                    .Any(l => l.LeadDimensionType == leadConnResourceParams.LeadDimensionType));

                result = leadConnResourceParams.Si == -1 ?
                    result : result.Where(t => t.Lead.LeadConnectors
                    .Any(l => l.Si == leadConnResourceParams.Si));
            }

            // ---------------Winding Information---------------
            if (trResourceParams.Winding != null)
            {
                // ---------------HVRWinding Information---------------
                if (trResourceParams.Winding.HVRWinding != null)
                {
                    var hvrWindingResourceParams = trResourceParams.Winding.HVRWinding;

                    result = string.IsNullOrEmpty(hvrWindingResourceParams.HVRWindingType) ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.HVRWindingType == hvrWindingResourceParams.HVRWindingType));

                    result = string.IsNullOrEmpty(hvrWindingResourceParams.WindingDirection) ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.WindingDirection == hvrWindingResourceParams.WindingDirection));

                    result = hvrWindingResourceParams.StripNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.StripNumber == hvrWindingResourceParams.StripNumber));

                    result = hvrWindingResourceParams.SpacerNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.SpacerNumber == hvrWindingResourceParams.SpacerNumber));

                    result = hvrWindingResourceParams.SpacerWidth == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.SpacerWidth == hvrWindingResourceParams.SpacerWidth));

                    result = hvrWindingResourceParams.ConductorNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.ConductorNumber == hvrWindingResourceParams.ConductorNumber));

                    result = hvrWindingResourceParams.HVRStepNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.HVRStepNumber == hvrWindingResourceParams.HVRStepNumber));

                    result = hvrWindingResourceParams.TopKsNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.TopKsNumber == hvrWindingResourceParams.TopKsNumber));

                    result = hvrWindingResourceParams.AngleRingNumber == -1 ?
                        result : result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.AngleRingNumber == hvrWindingResourceParams.AngleRingNumber));

                    result = hvrWindingResourceParams.HasFSA ?
                       result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.HasFSA == true)) :
                        result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.HasFSA == false));

                    result = hvrWindingResourceParams.IsUniformInsulation ?
                       result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsUniformInsulation == true)) :
                        result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsUniformInsulation == false));

                    result = hvrWindingResourceParams.IsCTC ?
                       result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsCTC == true)) :
                        result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsCTC == false));

                    result = hvrWindingResourceParams.IsDivided ?
                       result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsDivided == true)) :
                        result.Where(t => t.Winding.HVRWindings
                        .Any(w => w.IsDivided == false));
                }

                // ---------------DiscWinding Information---------------
                if (trResourceParams.Winding.DiscWinding != null)
                {
                    var discWindingResourceParams = trResourceParams.Winding.DiscWinding;

                    result = string.IsNullOrEmpty(discWindingResourceParams.WindingName) ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.WindingName == discWindingResourceParams.WindingName));

                    result = string.IsNullOrEmpty(discWindingResourceParams.DiscWindingType) ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.DiscWindingType == discWindingResourceParams.DiscWindingType));

                    result = string.IsNullOrEmpty(discWindingResourceParams.WindingDirection) ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.WindingDirection == discWindingResourceParams.WindingDirection));

                    result = discWindingResourceParams.StripNumber == -1 ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.StripNumber == discWindingResourceParams.StripNumber));

                    result = discWindingResourceParams.SpacerNumber == -1 ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.SpacerNumber == discWindingResourceParams.SpacerNumber));

                    result = discWindingResourceParams.SpacerWidth == -1 ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.SpacerWidth == discWindingResourceParams.SpacerWidth));

                    result = discWindingResourceParams.ConductorNumber == -1 ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.ConductorNumber == discWindingResourceParams.ConductorNumber));

                    result = discWindingResourceParams.OilDeflectorNumber == -1 ?
                        result : result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.OilDeflectorNumber == discWindingResourceParams.OilDeflectorNumber));

                    result = discWindingResourceParams.ConductorStrandNumber == -1 ?
                       result : result.Where(t => t.Winding.DiscWindings
                       .Any(w => w.ConductorStrandNumber == discWindingResourceParams.ConductorStrandNumber));

                    result = discWindingResourceParams.HasFSA ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasFSA == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasFSA == false));

                    result = discWindingResourceParams.IsUniformInsulation ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsUniformInsulation == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsUniformInsulation == false));

                    result = discWindingResourceParams.IsCTC ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsCTC == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsCTC == false));

                    result = discWindingResourceParams.HasBananaSpacer ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasBananaSpacer == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasBananaSpacer == false));

                    result = discWindingResourceParams.HasSecondDiscOut ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasSecondDiscOut == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasSecondDiscOut == false));

                    result = discWindingResourceParams.IsSandwichInterleaved ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsSandwichInterleaved == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsSandwichInterleaved == false));

                    result = discWindingResourceParams.IsInterleaved ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsInterleaved == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsInterleaved == false));

                    result = discWindingResourceParams.IsDivided ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsDivided == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.IsDivided == false));

                    result = discWindingResourceParams.HasLeadingPlate ?
                       result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasLeadingPlate == true)) :
                        result.Where(t => t.Winding.DiscWindings
                        .Any(w => w.HasLeadingPlate == false));
                }

                // ---------------LayerWinding Information---------------
                if (trResourceParams.Winding.LayerWinding != null)
                {
                    var layerWindingResourceParams = trResourceParams.Winding.LayerWinding;

                    result = string.IsNullOrEmpty(layerWindingResourceParams.WindingName) ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.WindingName == layerWindingResourceParams.WindingName));

                    result = string.IsNullOrEmpty(layerWindingResourceParams.LayerWindingType) ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.LayerWindingType == layerWindingResourceParams.LayerWindingType));

                    result = string.IsNullOrEmpty(layerWindingResourceParams.InnerLayerDirection) ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.InnerLayerDirection == layerWindingResourceParams.InnerLayerDirection));

                    result = layerWindingResourceParams.StripNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.StripNumber == layerWindingResourceParams.StripNumber));

                    result = layerWindingResourceParams.SpacerNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.SpacerNumber == layerWindingResourceParams.SpacerNumber));

                    result = layerWindingResourceParams.SpacerWidth == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.SpacerWidth == layerWindingResourceParams.SpacerWidth));

                    result = layerWindingResourceParams.AsialConductorNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.AsialConductorNumber == layerWindingResourceParams.AsialConductorNumber));

                    result = layerWindingResourceParams.RadialConductorNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.RadialConductorNumber == layerWindingResourceParams.RadialConductorNumber));

                    result = layerWindingResourceParams.OilDeflectorNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.OilDeflectorNumber == layerWindingResourceParams.OilDeflectorNumber));

                    result = layerWindingResourceParams.InnerCylinderNumber == -1 ?
                        result : result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.InnerCylinderNumber == layerWindingResourceParams.InnerCylinderNumber));

                    result = layerWindingResourceParams.HasFSA ?
                       result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.HasFSA == true)) :
                        result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.HasFSA == false));

                    result = layerWindingResourceParams.IsUniformInsulation ?
                       result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsUniformInsulation == true)) :
                        result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsUniformInsulation == false));

                    result = layerWindingResourceParams.HasCoreShielding ?
                       result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.HasCoreShielding == true)) :
                        result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.HasCoreShielding == false));

                    result = layerWindingResourceParams.IsLever ?
                       result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsLever == true)) :
                        result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsLever == false));

                    result = layerWindingResourceParams.IsDivided ?
                       result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsDivided == true)) :
                        result.Where(t => t.Winding.LayerWindings
                        .Any(w => w.IsDivided == false));
                }
            }

            // ---------------ActivePart Information---------------
            if (trResourceParams.ActivePart != null)
            {
                var activePartResourceParams = trResourceParams.ActivePart;

                result = activePartResourceParams.StripNumber == -1 ?
                    result : result.Where(t => t.ActivePart.StripNumber
                    == activePartResourceParams.StripNumber);

                result = activePartResourceParams.SpacerNumber == -1 ?
                    result : result.Where(t => t.ActivePart.SpacerNumber
                    == activePartResourceParams.SpacerNumber);

                result = activePartResourceParams.RatedVotage == -1 ?
                    result : result.Where(t => t.ActivePart.RatedVotage
                    == activePartResourceParams.RatedVotage);

                result = activePartResourceParams.WindingNumber == -1 ?
                    result : result.Where(t => t.ActivePart.WindingNumber
                    == activePartResourceParams.WindingNumber);

                result = string.IsNullOrEmpty(activePartResourceParams.HVRType) ?
                    result : result.Where(t => t.ActivePart.HVRType
                    == activePartResourceParams.HVRType);

                result = string.IsNullOrEmpty(activePartResourceParams.InnestWindingType) ?
                    result : result.Where(t => t.ActivePart.InnestWindingType
                    == activePartResourceParams.InnestWindingType);

                result = activePartResourceParams.HVAC == -1 ?
                    result : result.Where(t => t.ActivePart.HVAC
                    == activePartResourceParams.HVAC);

                result = activePartResourceParams.IsCenterInfeed ?
                    result.Where(t => t.ActivePart.IsCenterInfeed == true)
                    : result.Where(t => t.ActivePart.IsCenterInfeed == false);

                result = activePartResourceParams.IsUniformInsulation ?
                    result.Where(t => t.ActivePart.IsUniformInsulation == true)
                    : result.Where(t => t.ActivePart.IsUniformInsulation == false);

                result = activePartResourceParams.HasOD ?
                    result.Where(t => t.ActivePart.HasOD == true)
                    : result.Where(t => t.ActivePart.HasOD == false);
            }

            return result;
        }

        public async Task<Transformer> GetTransformerAsync(Guid transformerId)
        {
            return await _context.Transformers
                    .Include(t => t.Tank)
                    .Include(t => t.Conservator)
                    .Include(t => t.BasicInfos)
                    .Include(t => t.BasicInfos.TapChangers)
                    .Include(t => t.BasicInfos.Domes)
                    .Include(t => t.BasicInfos.Bushings)
                    .Include(t => t.CoolingSystem)
                    .Include(t => t.Accessories)
                    .Include(t => t.Accessories.AccesstoryEquipments)
                    .Include(t => t.Lead)
                    .Include(t => t.Lead.LeadConnectors)
                    .Include(t => t.Winding)
                    .Include(t => t.Winding.HVRWindings)
                    .Include(t => t.Winding.DiscWindings)
                    .Include(t => t.Winding.LayerWindings)
                    .Include(t => t.ActivePart)
                    .FirstOrDefaultAsync(t => t.Id == transformerId);
        }

        public async Task<BasicInfos> GetBasicInfosAsync(Guid transformerId)
        {
            return await _context.BasicInfos
                .Include(b => b.TapChangers)
                .Include(b => b.Domes)
                .Include(b => b.Bushings)
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<Tank> GetTankAsync(Guid transformerId)
        {
            return await _context.Tanks
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<Conservator> GetConservatorAsync(Guid transformerId)
        {
            return await _context.Conservators
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<CoolingSystem> GetCoolingSystemAsync(Guid transformerId)
        {
            return await _context.CoolingSystems
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<Accessories> GetAccessoriesAsync(Guid transformerId)
        {
            return await _context.Accessories
                .Include(t => t.AccesstoryEquipments)
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<Lead> GetLeadAsync(Guid transformerId)
        {
            return await _context.Leads
                .Include(l => l.LeadConnectors)
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<Winding> GetWindingAsync(Guid transformerId)
        {
            return await _context.Windings
                .Include(w => w.DiscWindings)
                .Include(w => w.LayerWindings)
                .Include(w => w.HVRWindings)
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<ActivePart> GetActivePartAsync(Guid transformerId)
        {
            return await _context.ActiveParts
                .FirstOrDefaultAsync(t => t.TransformerId == transformerId);
        }

        public async Task<IEnumerable<Transformer>> GetTransformerByIdsAsync(IEnumerable<Guid> ids)
        {
            return await _context.Transformers
                    .Include(t => t.Tank)
                    .Include(t => t.Conservator)
                    .Include(t => t.BasicInfos)
                    .Include(t => t.BasicInfos.TapChangers)
                    .Include(t => t.BasicInfos.Domes)
                    .Include(t => t.BasicInfos.Bushings)
                    .Include(t => t.CoolingSystem)
                    .Include(t => t.Accessories)
                    .Include(t => t.Accessories.AccesstoryEquipments)
                    .Include(t => t.Lead)
                    .Include(t => t.Lead.LeadConnectors)
                    .Include(t => t.Winding)
                    .Include(t => t.Winding.HVRWindings)
                    .Include(t => t.Winding.DiscWindings)
                    .Include(t => t.Winding.LayerWindings)
                    .Include(t => t.ActivePart)
                    .Where(t => ids.Contains(t.Id))
                    .ToListAsync();
        }

        public async Task<PaginationList<Transformer>> GetTransformersAsync(
            TransformerResourceParameters trResourceParams,
            PaginationResourceParameters paginationParams)
        {
            IQueryable<Transformer> result = _context.Transformers
                    .Include(t => t.Tank)
                    .Include(t => t.Conservator)
                    .Include(t => t.BasicInfos)
                    .Include(t => t.BasicInfos.TapChangers)
                    .Include(t => t.BasicInfos.Domes)
                    .Include(t => t.BasicInfos.Bushings)
                    .Include(t => t.CoolingSystem)
                    .Include(t => t.Accessories)
                    .Include(t => t.Accessories.AccesstoryEquipments)
                    .Include(t => t.Lead)
                    .Include(t => t.Lead.LeadConnectors)
                    .Include(t => t.Winding)
                    .Include(t => t.Winding.HVRWindings)
                    .Include(t => t.Winding.DiscWindings)
                    .Include(t => t.Winding.LayerWindings)
                    .Include(t => t.ActivePart);

            result = ConditionalFileter(trResourceParams, result);

            result = result.OrderByDescending(t => t.BasicInfos.ProjectNumber);

            return await PaginationList<Transformer>.CreateAsync(
                paginationParams.PageNumber,
                paginationParams.PageSize,
                result);
        }

        public async Task<PaginationList<Transformer>> GetTransformersAsync(
            PaginationResourceParameters paginationParams)
        {
            IQueryable<Transformer> result = _context.Transformers
                    .Include(t => t.Tank)
                    .Include(t => t.Conservator)
                    .Include(t => t.BasicInfos)
                    .Include(t => t.BasicInfos.TapChangers)
                    .Include(t => t.BasicInfos.Domes)
                    .Include(t => t.BasicInfos.Bushings)
                    .Include(t => t.CoolingSystem)
                    .Include(t => t.Accessories)
                    .Include(t => t.Accessories.AccesstoryEquipments)
                    .Include(t => t.Lead)
                    .Include(t => t.Lead.LeadConnectors)
                    .Include(t => t.Winding)
                    .Include(t => t.Winding.HVRWindings)
                    .Include(t => t.Winding.DiscWindings)
                    .Include(t => t.Winding.LayerWindings)
                    .Include(t => t.ActivePart);

            result = result.OrderByDescending(t => t.BasicInfos.ProjectNumber);

            return await PaginationList<Transformer>.CreateAsync(
                paginationParams.PageNumber,
                paginationParams.PageSize,
                result);
        }

        public void AddTransformer(Transformer transformer)
        {
            if (transformer == null)
            {
                throw new ArgumentNullException(nameof(transformer));
            }
                
            _context.Transformers
                .Add(transformer);
        }

        public async Task<bool> CheckTransformerExistAsync(Guid transformerId)
        {
            return await _context.Transformers
                .AnyAsync(t => t.Id == transformerId);
        }


        public async Task<bool> CheckTransformerExistByProjectNumberAsync(string projectNumber)
        {
            return await _context.Transformers
                .AnyAsync(t => t.BasicInfos.ProjectNumber == projectNumber);
        }

        public void DeleteTransformer(Transformer transformer)
        {
            if (transformer == null)
            {
                throw new ArgumentNullException(nameof(transformer));
            }

            _context.Transformers
                .Remove(transformer);
        }

        public void DeleteTransformers(IEnumerable<Transformer> transformers)
        {
            _context.Transformers
                .RemoveRange(transformers);
        }

        public async Task<int> GetTransformersNumAsync(
            string regionType, 
            DateTime from, 
            DateTime end)
        {
            IQueryable<Transformer> result = _context.Transformers
                .Include(t => t.BasicInfos)
                .Where(t => t.BasicInfos.RegionType == regionType);

            // 若设置了起始时间
            if(from != null)
            {
                result = result.Where(t => t.BasicInfos.ManufactureDate.Date >= from);
            }

            // 若未设置截止时间
            if(end == null)
            {
                end = DateTime.Today;
            }

            return await result
                .Where(t => t.BasicInfos.ManufactureDate.Date <= end)
                .CountAsync();
        }

        public async Task<bool> SaveChangesAsync()
        {
            return (await _context.SaveChangesAsync() >= 0);
        }
    }
}
